{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# 数据计算与转换\n",
    "\n",
    "## 核心操作速查\n",
    "\n",
    "| 操作类别 | 方法 | 说明 |\n",
    "|----------|------|------|\n",
    "| **算术运算** | `+`, `-`, `*`, `/`, `**` | 向量化运算 |\n",
    "| **统计函数** | `sum()`, `mean()`, `std()` | 快速统计 |\n",
    "| **聚合** | `agg()`, `groupby()` | 分组聚合 |\n",
    "| **透视表** | `pivot_table()` | Excel透视表 |\n",
    "| **宽转长** | `melt()` | 列转行 |\n",
    "| **重塑** | `stack()`, `unstack()` | 索引转换 |\n",
    "\n",
    "---\n",
    "\n",
    "## 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "load-data",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 加载示例数据（使用第六讲生成的数据）\n",
    "try:\n",
    "    students = pd.read_csv('../data/demo/students.csv')\n",
    "    orders = pd.read_csv('../data/demo/orders.csv')\n",
    "    print(\"✓ 数据加载成功\")\n",
    "    print(f\"学生数据: {students.shape}\")\n",
    "    print(f\"订单数据: {orders.shape}\")\n",
    "except FileNotFoundError:\n",
    "    print(\"请先运行第六讲生成示例数据\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "arithmetic",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 一、算术运算\n",
    "\n",
    "### 向量化运算\n",
    "\n",
    "Pandas可以直接对整列数据进行运算，无需循环\n",
    "\n",
    "| 运算符 | 说明 | 示例 |\n",
    "|--------|------|------|\n",
    "| `+` | 加法 | `df['A'] + df['B']` |\n",
    "| `-` | 减法 | `df['A'] - df['B']` |\n",
    "| `*` | 乘法 | `df['A'] * 2` |\n",
    "| `/` | 除法 | `df['A'] / df['B']` |\n",
    "| `**` | 幂运算 | `df['A'] ** 2` |\n",
    "| `%` | 取余 | `df['A'] % 10` |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "arithmetic-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 算术运算示例 ===\")\n",
    "\n",
    "# 1. 基础计算\n",
    "orders['折扣率'] = ((orders['订单金额'] - orders['订单金额'] * 0.9) / orders['订单金额'] * 100).round(2)\n",
    "orders['利润'] = (orders['订单金额'] * 0.3).round(2)\n",
    "orders['成本'] = (orders['订单金额'] - orders['利润']).round(2)\n",
    "\n",
    "print(\"\\n计算结果示例:\")\n",
    "print(orders[['订单金额', '成本', '利润', '折扣率']].head())\n",
    "\n",
    "# 2. 多列运算\n",
    "print(\"\\n基础统计:\")\n",
    "print(f\"总订单金额: {orders['订单金额'].sum():.2f}元\")\n",
    "print(f\"总利润: {orders['利润'].sum():.2f}元\")\n",
    "print(f\"平均订单金额: {orders['订单金额'].mean():.2f}元\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "stats",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 二、统计函数\n",
    "\n",
    "### 常用统计方法\n",
    "\n",
    "| 函数 | 功能 | 示例 |\n",
    "|------|------|------|\n",
    "| `count()` | 非空值计数 | `df['col'].count()` |\n",
    "| `sum()` | 求和 | `df['col'].sum()` |\n",
    "| `mean()` | 平均值 | `df['col'].mean()` |\n",
    "| `median()` | 中位数 | `df['col'].median()` |\n",
    "| `std()` | 标准差 | `df['col'].std()` |\n",
    "| `min()` / `max()` | 最小/最大值 | `df['col'].min()` |\n",
    "| `quantile()` | 分位数 | `df['col'].quantile(0.25)` |\n",
    "| `describe()` | 综合统计 | `df.describe()` |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "stats-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 统计函数示例 ===\")\n",
    "\n",
    "# 1. 基础统计\n",
    "print(\"\\n订单金额统计:\")\n",
    "print(f\"订单数量: {orders['订单金额'].count()}\")\n",
    "print(f\"总金额: {orders['订单金额'].sum():.2f}\")\n",
    "print(f\"平均值: {orders['订单金额'].mean():.2f}\")\n",
    "print(f\"中位数: {orders['订单金额'].median():.2f}\")\n",
    "print(f\"标准差: {orders['订单金额'].std():.2f}\")\n",
    "print(f\"最小值: {orders['订单金额'].min():.2f}\")\n",
    "print(f\"最大值: {orders['订单金额'].max():.2f}\")\n",
    "\n",
    "# 2. describe()综合统计\n",
    "print(\"\\n综合统计信息:\")\n",
    "print(orders['订单金额'].describe())\n",
    "\n",
    "# 3. 分位数\n",
    "print(\"\\n分位数分析:\")\n",
    "print(f\"25%分位数: {orders['订单金额'].quantile(0.25):.2f}\")\n",
    "print(f\"50%分位数: {orders['订单金额'].quantile(0.50):.2f}\")\n",
    "print(f\"75%分位数: {orders['订单金额'].quantile(0.75):.2f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "agg",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 三、聚合函数 (agg)\n",
    "\n",
    "### agg() 的强大之处\n",
    "\n",
    "可以对不同列应用不同的聚合函数\n",
    "\n",
    "| 用法 | 说明 | 示例 |\n",
    "|------|------|------|\n",
    "| 单列单函数 | `df['col'].agg('sum')` | 求和 |\n",
    "| 单列多函数 | `df['col'].agg(['sum', 'mean'])` | 多个统计 |\n",
    "| 多列同函数 | `df[['A', 'B']].agg('sum')` | 多列求和 |\n",
    "| 多列异函数 | `df.agg({'A': 'sum', 'B': 'mean'})` | 不同统计 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "agg-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 聚合函数示例 ===\")\n",
    "\n",
    "# 1. 单列多个聚合\n",
    "result1 = orders['订单金额'].agg(['sum', 'mean', 'max', 'min'])\n",
    "print(\"\\n单列多个聚合:\")\n",
    "print(result1)\n",
    "\n",
    "# 2. 多列不同聚合\n",
    "result2 = orders.agg({\n",
    "    '订单金额': ['sum', 'mean'],\n",
    "    '评分': ['mean', 'count']\n",
    "})\n",
    "print(\"\\n多列不同聚合:\")\n",
    "print(result2)\n",
    "\n",
    "# 3. 自定义聚合函数\n",
    "def value_range(x):\n",
    "    return x.max() - x.min()\n",
    "\n",
    "result3 = orders['订单金额'].agg(['min', 'max', value_range])\n",
    "print(\"\\n自定义聚合函数:\")\n",
    "print(result3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "groupby",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 四、分组聚合 (groupby)\n",
    "\n",
    "### groupby工作流程\n",
    "\n",
    "```\n",
    "原始数据 → Split（分组） → Apply（应用函数） → Combine（合并结果）\n",
    "```\n",
    "\n",
    "### 常用模式\n",
    "\n",
    "| 模式 | 语法 | 说明 |\n",
    "|------|------|------|\n",
    "| 单列分组 | `df.groupby('col')` | 按一列分组 |\n",
    "| 多列分组 | `df.groupby(['col1', 'col2'])` | 按多列分组 |\n",
    "| 聚合 | `df.groupby('col').agg()` | 分组后聚合 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "groupby-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 分组聚合示例 ===\")\n",
    "\n",
    "# 合并学生和订单数据\n",
    "merged = orders.merge(students[['学生ID', '专业', '年级']], on='学生ID')\n",
    "\n",
    "# 1. 单列分组\n",
    "by_major = merged.groupby('专业').agg({\n",
    "    '订单ID': 'count',\n",
    "    '订单金额': ['sum', 'mean']\n",
    "})\n",
    "by_major.columns = ['订单数', '总金额', '平均金额']\n",
    "print(\"\\n按专业分组统计:\")\n",
    "print(by_major.round(2))\n",
    "\n",
    "# 2. 多列分组\n",
    "by_major_grade = merged.groupby(['专业', '年级']).agg({\n",
    "    '订单ID': 'count',\n",
    "    '订单金额': 'sum'\n",
    "})\n",
    "by_major_grade.columns = ['订单数', '总金额']\n",
    "print(\"\\n按专业和年级分组:\")\n",
    "print(by_major_grade.head(10).round(2))\n",
    "\n",
    "# 3. 按类别分组\n",
    "by_category = orders.groupby('商品类别').agg({\n",
    "    '订单ID': 'count',\n",
    "    '订单金额': 'sum'\n",
    "}).sort_values('订单金额', ascending=False)\n",
    "by_category.columns = ['订单数', '总销售额']\n",
    "print(\"\\n按商品类别分组:\")\n",
    "print(by_category.round(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "pivot",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 五、数据透视表 (pivot_table)\n",
    "\n",
    "### 透视表参数\n",
    "\n",
    "| 参数 | 说明 | 示例 |\n",
    "|------|------|------|\n",
    "| `index` | 行索引 | 分组的行标签 |\n",
    "| `columns` | 列索引 | 分组的列标签 |\n",
    "| `values` | 值 | 要聚合的数据列 |\n",
    "| `aggfunc` | 聚合函数 | sum/mean/count等 |\n",
    "| `margins` | 总计 | True显示总计行列 |\n",
    "\n",
    "### Excel透视表对应\n",
    "\n",
    "- **index** = Excel的\"行\"区域\n",
    "- **columns** = Excel的\"列\"区域\n",
    "- **values** = Excel的\"值\"区域\n",
    "- **aggfunc** = Excel的\"汇总方式\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "pivot-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 数据透视表示例 ===\")\n",
    "\n",
    "# 1. 简单透视表\n",
    "pivot1 = pd.pivot_table(\n",
    "    merged,\n",
    "    index='专业',\n",
    "    columns='商品类别',\n",
    "    values='订单金额',\n",
    "    aggfunc='sum'\n",
    ")\n",
    "print(\"\\n专业×商品类别的销售额:\")\n",
    "print(pivot1.round(2))\n",
    "\n",
    "# 2. 带总计的透视表\n",
    "pivot2 = pd.pivot_table(\n",
    "    merged,\n",
    "    index='专业',\n",
    "    columns='年级',\n",
    "    values='订单金额',\n",
    "    aggfunc='sum',\n",
    "    margins=True,\n",
    "    margins_name='总计'\n",
    ")\n",
    "print(\"\\n专业×年级的销售额（含总计):\")\n",
    "print(pivot2.round(2))\n",
    "\n",
    "# 3. 多值透视表\n",
    "pivot3 = pd.pivot_table(\n",
    "    merged,\n",
    "    index='专业',\n",
    "    values=['订单金额'],\n",
    "    aggfunc={'订单金额': ['sum', 'mean', 'count']}\n",
    ")\n",
    "pivot3.columns = ['总销售额', '平均订单额', '订单数']\n",
    "print(\"\\n各专业综合统计:\")\n",
    "print(pivot3.round(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "reshape",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 六、数据重塑\n",
    "\n",
    "### 宽表与长表\n",
    "\n",
    "- **宽表**：数据横向展开（如月度销售按月份列展开）\n",
    "- **长表**：数据纵向展开（每行一条记录）\n",
    "\n",
    "### 转换方法\n",
    "\n",
    "| 方法 | 功能 | 说明 |\n",
    "|------|------|------|\n",
    "| `melt()` | 宽→长 | 列转为行 |\n",
    "| `pivot()` | 长→宽 | 行转为列 |\n",
    "| `stack()` | 列索引→行索引 | 压缩 |\n",
    "| `unstack()` | 行索引→列索引 | 解压 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reshape-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"=== 数据重塑示例 ===\")\n",
    "\n",
    "# 1. melt：宽表转长表\n",
    "wide_df = pd.DataFrame({\n",
    "    '姓名': ['张三', '李四'],\n",
    "    '语文': [85, 90],\n",
    "    '数学': [92, 88],\n",
    "    '英语': [78, 95]\n",
    "})\n",
    "\n",
    "long_df = wide_df.melt(\n",
    "    id_vars=['姓名'],\n",
    "    var_name='科目',\n",
    "    value_name='成绩'\n",
    ")\n",
    "\n",
    "print(\"\\n宽表:\")\n",
    "print(wide_df)\n",
    "print(\"\\n转换为长表:\")\n",
    "print(long_df)\n",
    "\n",
    "# 2. pivot：长表转宽表\n",
    "back_to_wide = long_df.pivot(\n",
    "    index='姓名',\n",
    "    columns='科目',\n",
    "    values='成绩'\n",
    ")\n",
    "print(\"\\n重新转回宽表:\")\n",
    "print(back_to_wide)\n",
    "\n",
    "# 3. stack和unstack\n",
    "df_multi = pivot1  # 使用之前的透视表\n",
    "\n",
    "print(\"\\n原始数据（宽格式）:\")\n",
    "print(df_multi.head())\n",
    "\n",
    "stacked = df_multi.stack()\n",
    "print(\"\\nstack后（长格式）:\")\n",
    "print(stacked.head(10))\n",
    "\n",
    "unstacked = stacked.unstack()\n",
    "print(\"\\nunstack后（恢复宽格式）:\")\n",
    "print(unstacked.head())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "summary",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 操作速查表\n",
    "\n",
    "### 完整语法\n",
    "\n",
    "```python\n",
    "# 1. 算术运算\n",
    "df['new'] = df['col1'] + df['col2']       # 加法\n",
    "df['new'] = df['col'] * 0.3               # 乘法\n",
    "df['new'] = (df['col1'] / df['col2']).round(2)  # 除法并四舍五入\n",
    "\n",
    "# 2. 统计函数\n",
    "df['col'].sum()                           # 求和\n",
    "df['col'].mean()                          # 平均值\n",
    "df['col'].describe()                      # 综合统计\n",
    "\n",
    "# 3. 聚合\n",
    "df['col'].agg(['sum', 'mean'])           # 单列多函数\n",
    "df.agg({'A': 'sum', 'B': 'mean'})        # 多列不同函数\n",
    "\n",
    "# 4. 分组聚合\n",
    "df.groupby('col').agg({'val': 'sum'})    # 分组求和\n",
    "df.groupby(['A', 'B']).agg('mean')       # 多列分组\n",
    "\n",
    "# 5. 透视表\n",
    "pd.pivot_table(\n",
    "    df,\n",
    "    index='行',\n",
    "    columns='列',\n",
    "    values='值',\n",
    "    aggfunc='sum',\n",
    "    margins=True\n",
    ")\n",
    "\n",
    "# 6. 数据重塑\n",
    "df.melt(id_vars=['id'], var_name='变量', value_name='值')  # 宽→长\n",
    "df.pivot(index='行', columns='列', values='值')            # 长→宽\n",
    "df.stack()                                                 # 列→行索引\n",
    "df.unstack()                                               # 行→列索引\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "## 小结\n",
    "\n",
    "**核心技能**:\n",
    "1. **算术运算**: 向量化操作,高效快速\n",
    "2. **统计函数**: 快速获取数据特征\n",
    "3. **聚合**: 灵活的多列多函数聚合\n",
    "4. **分组**: Split-Apply-Combine模式\n",
    "5. **透视表**: Excel透视表的强化版\n",
    "6. **数据重塑**: 灵活转换数据格式\n",
    "\n",
    "**实用技巧**:\n",
    "- 运算时注意处理空值和除零错误\n",
    "- 使用`agg()`可以一次性完成多种统计\n",
    "- 透视表的`margins=True`可显示总计\n",
    "- `melt()`和`pivot()`互为逆操作\n",
    "\n",
    "**下一步**: 学习分组与聚合的高级操作"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
